package com.zhilehuo.pretask.ui.article

import android.content.Context
import android.graphics.Color
import android.media.AudioManager
import android.media.MediaPlayer
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.PagerSnapHelper
import com.zhilehuo.pretask.adapter.ArticlePagerAdapter
import com.zhilehuo.pretask.databinding.FragmentArticleBinding
import android.os.Handler
import android.os.Looper
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.recyclerview.widget.RecyclerView
import com.zhilehuo.pretask.R

/**
 * @Description: 读一读页面
 * @Author: Realnt
 * @Date:
 */
class ArticleFragment : Fragment(), MediaPlayer.OnPreparedListener {
    private lateinit var binding: FragmentArticleBinding
    private val viewModel: ArticleViewModel by viewModels()
    private var mediaPlayer: MediaPlayer? = null
    private var handler: Handler? = null
    private var highlightRunnable: Runnable? = null
    private lateinit var articlePagerAdapter: ArticlePagerAdapter

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        /* 设置系统状态栏为白色 */
        val window = requireActivity().window
        val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
        windowInsetsController.isAppearanceLightStatusBars = true
        windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
        requireActivity().window.statusBarColor = Color.parseColor("#FFFFFF")

        articlePagerAdapter = ArticlePagerAdapter(this ,viewModel) // 把fragment和viewModel引用传给adapter
        binding = FragmentArticleBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setupRecyclerView() // 初始化RecyclerView
        observeViewModel()  // 建立数据观察
        viewModel.loadArticle(6) // 加载aid=6的数据
        viewModel.errorMessage.observe(viewLifecycleOwner){
            error -> Toast.makeText(context, error, Toast.LENGTH_SHORT).show()
        }

        /* 页面加载完成后立即播放音频并开始高亮文字 */
        viewModel.articleData.observe(viewLifecycleOwner) { article ->
            if (article != null) {
                playPageAudio(0)
                startHighlighting()
                setProgressBarWidth(1, 7) // 加载当前页面进度
            }
        }
    }

    /**
     * @Description: 初始化RecyclerView
     * @Param  :
     * @Return  :
     */
    private fun setupRecyclerView() {
        binding.rvPager.apply {
            layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) // 水平线性布局管理器
            adapter = ArticlePagerAdapter(this@ArticleFragment, viewModel).apply {
                onPageChangeListener = { page -> // 页面改变监听
                    viewModel.setCurrentPage(page)
                    playPageAudio(page) // 播放对应页面的音频
                    setProgressBarWidth(page + 1, 7)
                }
                /* 因为页面改变监听器不能保证触发(原因未知), 所以添加滚动监听器保证触发 */
                binding.rvPager.addOnScrollListener(object : RecyclerView.OnScrollListener() {
                    private var currentPage = -1
                    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                        /* 停止后再检测, 减少性能开销 */
                        if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                            val layoutManager = recyclerView.layoutManager as LinearLayoutManager
                            val newPage = layoutManager.findFirstVisibleItemPosition()

                            if (newPage != currentPage) {
                                currentPage = newPage
                                onPageChangeListener?.invoke(newPage)
                            }
                        }
                    }
                })
            }
            val pagerSnapHelper = PagerSnapHelper() // 页面固定
            pagerSnapHelper.attachToRecyclerView(binding.rvPager)
        }
    }

    /**
     * @Description: 播放页面音频
     * @Param page : 音频对应页
     * @Return  :
     */
    private fun playPageAudio(page: Int) {
        mediaPlayer?.release() // 先释放, 保证一次播放一个
        mediaPlayer = null

        val pageContent = viewModel.articleData.value?.contentList?.get(page)
        pageContent?.audioUrl?.let { url ->
            mediaPlayer = MediaPlayer().apply {
                setDataSource(url)
                prepareAsync()
                setOnPreparedListener(this@ArticleFragment)
                setOnCompletionListener { resetPlayState() }
            }
        }
    }

    /**
     * @Description: 重置播放状态
     * @Param  :
     * @Return  :
     */
    private fun resetPlayState() {
        mediaPlayer?.apply {
            stop()
            release()
        }
        mediaPlayer = null
        handler?.removeCallbacksAndMessages(null)
    }

    /**
     * @Description: 音频准备完成回调
     * @Param mp : 播放器
     * @Return  :
     */
    override fun onPrepared(mp: MediaPlayer) {
        mp.start()
        startHighlighting() // 开始跟随音频高亮文字
    }

    /**
     * @Description: 转换播放启动/暂停
     * @Param  :
     * @Return  :
     */
    fun togglePlayPause() {
        mediaPlayer?.let { player ->
            if (player.isPlaying) {
                player.pause()
                updatePlayButton(false)
            } else {
                player.start()
                updatePlayButton(true)
            }
        }
    }

    /**
     * @Description: 重播
     * @Param  :
     * @Return  :
     */
    fun replayCurrentPage() {
        mediaPlayer?.seekTo(0)
        mediaPlayer?.start()
        updatePlayButton(true)
    }

    /**
     * @Description: 调节音量
     * @Param  :
     * @Return  :
     */
    fun adjustVolume() {
        val audioManager = binding.root.context?.getSystemService(Context.AUDIO_SERVICE) as AudioManager
        audioManager.adjustStreamVolume(
            AudioManager.STREAM_MUSIC,
            AudioManager.ADJUST_SAME,
            AudioManager.FLAG_SHOW_UI
        )
    }

    /**
     * @Description: 改变播放按钮状态
     * @Param isPlaying : 是否正在播放
     * @Return  :
     */
    private fun updatePlayButton(isPlaying: Boolean) {
        val viewHolder = (binding.rvPager.findViewHolderForAdapterPosition(viewModel.currentPage.value ?: 0) as? ArticlePagerAdapter.PageViewHolder) //获取到ViewHolder
        viewHolder?.binding?.btnPlay?.icon = if (isPlaying) ContextCompat.getDrawable(requireContext(), R.drawable.play) else ContextCompat.getDrawable(requireContext(), R.drawable.stop)
    }

    /**
     * @Description: 开始高亮文字
     * @Param  :
     * @Return  :
     */
    private fun startHighlighting() {
        handler = Handler(Looper.getMainLooper())
        highlightRunnable = object : Runnable {
            override fun run() {
                mediaPlayer?.let { player ->
                    val currentPos = player.currentPosition
                    updateTextHighlight(currentPos) // 更新高亮状态
                    handler?.postDelayed(this, 50)
                }
            }
        }
        highlightRunnable?.let { handler?.post(it) }
    }

    /**
     * @Description: 更新文字高亮
     * @Param positionMs : 当前的位置对应的Ms
     * @Return  :
     */
    private fun updateTextHighlight(positionMs: Int) {
        val currentPage = viewModel.currentPage.value ?: 0
        val words = viewModel.articleData.value?.contentList?.get(currentPage)?.sentenceByXFList

        words?.let {
            val spannable = SpannableStringBuilder()
            var currentIndex = 0

            it.forEach { word ->
                val start = currentIndex
                val end = start + word.word.length
                spannable.append(word.word)

                // 判断是否当前高亮词
                if (positionMs >= word.wb && positionMs <= word.we) {
                    spannable.setSpan(
                        ForegroundColorSpan(Color.RED),
                        start,
                        end,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
                    )
                }
                currentIndex = end
            }
            val viewHolder = (binding.rvPager.findViewHolderForAdapterPosition(currentPage) as? ArticlePagerAdapter.PageViewHolder)
            viewHolder?.tvContent?.text = spannable
        }
    }

    /**
     * @Description: 观察ViewModel数据
     * @Param  :
     * @Return  :
     */
    private fun observeViewModel() {
        viewModel.articleData.observe(viewLifecycleOwner) { article ->
            (binding.rvPager.adapter as ArticlePagerAdapter).submitList(article.contentList)
        }

        viewModel.currentPage.observe(viewLifecycleOwner) { _ ->
            // 更新页码指示器等
        }
    }

    /**
     * @Description: 设置进度
     * @Param currentPage : 当前页
     * @Param totalPageCount : 总计页
     * @Return  :
     */
    private fun setProgressBarWidth(currentPage: Int, totalPageCount: Int) {
        val progressBar = binding.tvReadProcessLineChart

        val progressPercentage = (currentPage.toFloat() / totalPageCount) * 100 // 计算进度条的宽度百分比

        val parentWidth = binding.llReadProcess.width // 获取父布局的宽度

        val progressBarWidth = (parentWidth * progressPercentage / 100).toInt() // 设置进度条的宽度
        val layoutParams = progressBar.layoutParams
        layoutParams.width = progressBarWidth
        progressBar.layoutParams = layoutParams

        val readProcess = "${currentPage}/${totalPageCount}"
        binding.tvReadProcess.text = readProcess
    }

    /**
     * @Description: 释放资源
     * @Param  :
     * @Return  :
     */
    override fun onDestroy() {
        mediaPlayer?.release()
        handler?.removeCallbacksAndMessages(null)
        super.onDestroy()
    }
}